
package com.seaengine.net
{
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	public class TaskQueue extends EventDispatcher
	{
		private var _queue:Array ;
		
		private var _run:Function ;
		
		
		private var _timeDelay:Number = 1000;
		
		private var _autoRun:Boolean = false;
		
		private var _isRun:Boolean = false;
		
		private var _timer:Timer ;
		
		private var _realType:Class;
		
		private var _runCount:int = 0;
		
		private const OVER_TIME:int = 300;
		
		private const MAX_TASKS:int = 128;
		
		private var _target:IEventDispatcher;
		
		public function TaskQueue(target:IEventDispatcher=null)
		{
			super(target);
			_timer = new Timer(_timeDelay);
			_timer.addEventListener(TimerEvent.TIMER,onTimer);
		}
		
		/**
		 * 
		 * @param arg
		 * 
		 */
		public function addTask(arg:Object=null):void
		{
			_queue.push(arg);
			if(!_isRun && _autoRun)
			{
				start();
			}
		}
		
		/**
		 * 
		 * 
		 */
		public function removeAllTask():void
		{
			_isRun = false;
			if(_timer.running)
			{
				_timer.stop();
			}
			while(_queue.length)
			{
				_queue.pop();
			}
		}
		
		/**
		 * 
		 * @param arg
		 * @return 
		 * 
		 */
		public function removeTask(arg:Object):Object
		{
			for(var i:int = 0 ; i < _queue.length ; ++i)
			{
				if(_queue[i] == arg)
				{
					_queue.splice(i,1);
					return arg;
				}
			}
			return null;
		}
		
		/**
		 * 
		 * @param target  绑定的目标对象 
		 * @param work	  绑定目标对象的方法
		 * @param real	 绑定目标对象的参数的具体化类型
		 * 
		 */
		public function bind(target:IEventDispatcher,work:Function,real:Class=null):void
		{
			if(null != work)
				_run = work;
			
			if(real)
				_realType = real;
				
			if(!real)
				real = Object;
				
			_target = target;
			_queue =  [];
			target.addEventListener(TaskEvent.TASK_FAIL,onTaskFail);
			target.addEventListener(TaskEvent.TASK_SUCCEED,onTaskSucceed);
		}
		
		private function onTimer(e:Timer):void
		{
			if(_runCount > OVER_TIME)
			{
				dispatchEvent(new TaskEvent(TaskEvent.TASK_OVER_TIME));
			}
			start();
		}
		
		
		private function onTaskFail(e:TaskEvent):void
		{
			if(!_timer.running)
			{
				_timer.start();
			}
			++_runCount;
			//trace("package TaskQueue",e.reason);
		}
		
		private function onTaskSucceed(e:TaskEvent):void
		{
			_queue.shift();
			if(_timer.running)
			{
				_timer.stop();
			}
			_runCount = 0;
			if(0 == _queue.length)
			{
				dispatchEvent(new TaskEvent(TaskEvent.TASK_DONE));
				_isRun = false;
				return;
			}
			start();
		}
		
		public function set worker(f:Function):void
		{
			_run = f;
		}
		
		public function get worker():Function
		{
			return _run;
		}
		
		public function set autoRun(b:Boolean):void
		{
			_autoRun = b;
		}
		
		public function get autoRun():Boolean
		{
			return _autoRun;
		}
		
		public function get hasTask():Boolean
		{
			return (_queue.length != 0);
		}
		
		public function get isRun():Boolean
		{
			return _isRun;
		}
		
		public function set isRun(b:Boolean):void
		{
			_isRun = b;
		}
		
		/**
		 * 
		 * 
		 */
		public function start():void
		{
			if(_isRun)
			{
				return;
			}
			if(!_queue.length)
			{
				throw new Error("空任务队列");
			}
			_isRun = true;
			dispatchEvent(new TaskEvent(TaskEvent.TASK_BEGIN));
			try{
				var obj:* = _realType(_queue[0]);
				_run(obj);
			}catch(e:Error){
				_run(_queue[0]);
			}
		}
	}
}